bge-ui 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/datePicker/components/ActionRow.vue.d.ts +1051 -0
- package/dist/datePicker/components/Common/ArrowBtn.vue.d.ts +29 -0
- package/dist/datePicker/components/Common/InstanceWrap.vue.d.ts +29 -0
- package/dist/datePicker/components/Common/SelectionOverlay.vue.d.ts +55 -0
- package/dist/datePicker/components/DatePicker/DatePicker.vue.d.ts +1114 -0
- package/dist/datePicker/components/DatePicker/DpCalendar.vue.d.ts +1085 -0
- package/dist/datePicker/components/DatePicker/DpHeader.vue.d.ts +1103 -0
- package/dist/datePicker/components/DatePicker/date-picker.d.ts +35 -0
- package/dist/datePicker/components/DatepickerInput.vue.d.ts +1008 -0
- package/dist/datePicker/components/DatepickerMenu.vue.d.ts +1061 -0
- package/dist/datePicker/components/Icons/CalendarIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/CancelIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronDownIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronLeftIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronRightIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ChevronUpIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/ClockIcon.d.ts +9 -0
- package/dist/datePicker/components/Icons/index.d.ts +7 -0
- package/dist/datePicker/components/MonthPicker/MonthPicker.vue.d.ts +1071 -0
- package/dist/datePicker/components/MonthPicker/month-picker.d.ts +34 -0
- package/dist/datePicker/components/QuarterPicker/QuarterPicker.vue.d.ts +1043 -0
- package/dist/datePicker/components/QuarterPicker/quarter-picker.d.ts +25 -0
- package/dist/datePicker/components/TimePicker/TimeInput.vue.d.ts +1116 -0
- package/dist/datePicker/components/TimePicker/TimePicker.vue.d.ts +1087 -0
- package/dist/datePicker/components/TimePicker/TimePickerSolo.vue.d.ts +1036 -0
- package/dist/datePicker/components/TimePicker/time-picker-utils.d.ts +15 -0
- package/dist/datePicker/components/TimePicker/time-picker.d.ts +13 -0
- package/dist/datePicker/components/YearPicker/YearPicker.vue.d.ts +1040 -0
- package/dist/datePicker/components/YearPicker/year-picker.d.ts +9 -0
- package/dist/datePicker/components/shared/YearModePicker.vue.d.ts +1075 -0
- package/dist/datePicker/components/shared/month-quarter-picker.d.ts +29 -0
- package/dist/datePicker/composables/arrow-navigate.d.ts +26 -0
- package/dist/datePicker/composables/calendar-class.d.ts +8 -0
- package/dist/datePicker/composables/common.d.ts +6 -0
- package/dist/datePicker/composables/defaults.d.ts +37 -0
- package/dist/datePicker/composables/external-internal-mapper.d.ts +14 -0
- package/dist/datePicker/composables/flow.d.ts +10 -0
- package/dist/datePicker/composables/index.d.ts +14 -0
- package/dist/datePicker/composables/model.d.ts +17 -0
- package/dist/datePicker/composables/month-year.d.ts +10 -0
- package/dist/datePicker/composables/position.d.ts +25 -0
- package/dist/datePicker/composables/shared.d.ts +12 -0
- package/dist/datePicker/composables/slots.d.ts +10 -0
- package/dist/datePicker/composables/state.d.ts +8 -0
- package/dist/datePicker/composables/transition.d.ts +7 -0
- package/dist/datePicker/composables/validation.d.ts +12 -0
- package/dist/datePicker/constants/index.d.ts +43 -0
- package/dist/datePicker/datePicker.vue.d.ts +1006 -0
- package/dist/datePicker/directives/clickOutside.d.ts +2 -0
- package/dist/datePicker/index.vue.d.ts +1012 -0
- package/dist/datePicker/interfaces.d.ts +323 -0
- package/dist/datePicker/props.d.ts +865 -0
- package/dist/datePicker/utils/date-utils.d.ts +45 -0
- package/dist/datePicker/utils/defaults.d.ts +42 -0
- package/dist/datePicker/utils/timezone.d.ts +8 -0
- package/dist/datePicker/utils/type-guard.d.ts +1 -0
- package/dist/datePicker/utils/util.d.ts +57 -0
- package/dist/dialog/index.vue.d.ts +6 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +13008 -1250
- package/dist/style.css +1188 -1
- package/dist/tooltip/index.vue.d.ts +2 -2
- package/dist/tooltip/usePopper.d.ts +5 -5
- package/package.json +3 -2
- package/src/datePicker/components/ActionRow.vue +216 -0
- package/src/datePicker/components/Common/ArrowBtn.vue +42 -0
- package/src/datePicker/components/Common/InstanceWrap.vue +28 -0
- package/src/datePicker/components/Common/SelectionOverlay.vue +320 -0
- package/src/datePicker/components/DatePicker/DatePicker.vue +302 -0
- package/src/datePicker/components/DatePicker/DpCalendar.vue +405 -0
- package/src/datePicker/components/DatePicker/DpHeader.vue +332 -0
- package/src/datePicker/components/DatePicker/date-picker.ts +674 -0
- package/src/datePicker/components/DatepickerInput.vue +334 -0
- package/src/datePicker/components/DatepickerMenu.vue +424 -0
- package/src/datePicker/components/Icons/CalendarIcon.ts +40 -0
- package/src/datePicker/components/Icons/CancelIcon.ts +32 -0
- package/src/datePicker/components/Icons/ChevronDownIcon.ts +29 -0
- package/src/datePicker/components/Icons/ChevronLeftIcon.ts +29 -0
- package/src/datePicker/components/Icons/ChevronRightIcon.ts +29 -0
- package/src/datePicker/components/Icons/ChevronUpIcon.ts +29 -0
- package/src/datePicker/components/Icons/ClockIcon.ts +32 -0
- package/src/datePicker/components/Icons/index.ts +8 -0
- package/src/datePicker/components/MonthPicker/MonthPicker.vue +130 -0
- package/src/datePicker/components/MonthPicker/month-picker.ts +232 -0
- package/src/datePicker/components/QuarterPicker/QuarterPicker.vue +111 -0
- package/src/datePicker/components/QuarterPicker/quarter-picker.ts +153 -0
- package/src/datePicker/components/TimePicker/TimeInput.vue +477 -0
- package/src/datePicker/components/TimePicker/TimePicker.vue +265 -0
- package/src/datePicker/components/TimePicker/TimePickerSolo.vue +79 -0
- package/src/datePicker/components/TimePicker/time-picker-utils.ts +179 -0
- package/src/datePicker/components/TimePicker/time-picker.ts +112 -0
- package/src/datePicker/components/YearPicker/YearPicker.vue +70 -0
- package/src/datePicker/components/YearPicker/year-picker.ts +109 -0
- package/src/datePicker/components/shared/YearModePicker.vue +105 -0
- package/src/datePicker/components/shared/month-quarter-picker.ts +199 -0
- package/src/datePicker/composables/arrow-navigate.ts +191 -0
- package/src/datePicker/composables/calendar-class.ts +383 -0
- package/src/datePicker/composables/common.ts +25 -0
- package/src/datePicker/composables/defaults.ts +123 -0
- package/src/datePicker/composables/external-internal-mapper.ts +442 -0
- package/src/datePicker/composables/flow.ts +70 -0
- package/src/datePicker/composables/index.ts +14 -0
- package/src/datePicker/composables/model.ts +89 -0
- package/src/datePicker/composables/month-year.ts +72 -0
- package/src/datePicker/composables/position.ts +297 -0
- package/src/datePicker/composables/shared.ts +98 -0
- package/src/datePicker/composables/slots.ts +84 -0
- package/src/datePicker/composables/state.ts +25 -0
- package/src/datePicker/composables/transition.ts +18 -0
- package/src/datePicker/composables/validation.ts +312 -0
- package/src/datePicker/constants/index.ts +49 -0
- package/src/datePicker/datePicker.vue +554 -0
- package/src/datePicker/directives/clickOutside.ts +79 -0
- package/src/datePicker/index.vue +158 -0
- package/src/datePicker/interfaces.ts +404 -0
- package/src/datePicker/props.ts +173 -0
- package/src/datePicker/style/components/_ActionRow.scss +73 -0
- package/src/datePicker/style/components/_Calendar.scss +284 -0
- package/src/datePicker/style/components/_DatepickerInput.scss +109 -0
- package/src/datePicker/style/components/_DatepickerMenu.scss +213 -0
- package/src/datePicker/style/components/_MonthYearInput.scss +97 -0
- package/src/datePicker/style/components/_QuarterPicker.scss +53 -0
- package/src/datePicker/style/components/_SelectionOverlay.scss +142 -0
- package/src/datePicker/style/components/_TimeInput.scss +181 -0
- package/src/datePicker/style/components/_shared.scss +15 -0
- package/src/datePicker/style/main.scss +259 -0
- package/src/datePicker/utils/date-utils.ts +440 -0
- package/src/datePicker/utils/defaults.ts +327 -0
- package/src/datePicker/utils/timezone.ts +38 -0
- package/src/datePicker/utils/type-guard.ts +3 -0
- package/src/datePicker/utils/util.ts +322 -0
- package/src/dialog/index.vue +9 -0
- package/src/form/index.vue +2 -1
- package/src/index.ts +6 -2
- package/src/slider/index.vue +1 -1
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
import { computed, onMounted, ref, nextTick } from 'vue';
|
|
2
|
+
import {
|
|
3
|
+
add,
|
|
4
|
+
addDays,
|
|
5
|
+
addMonths,
|
|
6
|
+
getHours,
|
|
7
|
+
getMinutes,
|
|
8
|
+
getMonth,
|
|
9
|
+
getSeconds,
|
|
10
|
+
getYear,
|
|
11
|
+
set,
|
|
12
|
+
startOfWeek,
|
|
13
|
+
subMonths,
|
|
14
|
+
} from 'date-fns';
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
getDate,
|
|
18
|
+
getDaysInBetween,
|
|
19
|
+
getNextMonthYear,
|
|
20
|
+
isDateBefore,
|
|
21
|
+
isDateEqual,
|
|
22
|
+
resetDateTime,
|
|
23
|
+
setDateTime,
|
|
24
|
+
} from '../../utils/date-utils';
|
|
25
|
+
import { useDefaults, useModel, useValidation } from '../../composables';
|
|
26
|
+
import { getMapDate, isNumNullish } from '../../utils/util';
|
|
27
|
+
import { isNumberArray } from '../../utils/type-guard';
|
|
28
|
+
import { useTimePickerUtils } from '../../components/TimePicker/time-picker-utils';
|
|
29
|
+
import {
|
|
30
|
+
checkRangeAutoApply,
|
|
31
|
+
getRangeWithFixedDate,
|
|
32
|
+
handleMultiDatesSelect,
|
|
33
|
+
setPresetDate,
|
|
34
|
+
} from '../../composables/shared';
|
|
35
|
+
import { FlowStep } from '../../constants';
|
|
36
|
+
|
|
37
|
+
import type { ICalendarDate, ICalendarDay, WeekStartNum, IMarker, VueEmit, TimeType } from '../../interfaces';
|
|
38
|
+
import type { UnwrapRef } from 'vue';
|
|
39
|
+
import type { PickerBasePropsType } from '../../props';
|
|
40
|
+
import { dateToTimezoneSafe } from '../../utils/timezone';
|
|
41
|
+
|
|
42
|
+
export const useDatePicker = (
|
|
43
|
+
props: PickerBasePropsType,
|
|
44
|
+
emit: VueEmit,
|
|
45
|
+
triggerCalendarTransition: (inst?: number) => void,
|
|
46
|
+
updateFlow: () => void,
|
|
47
|
+
) => {
|
|
48
|
+
const tempRange = ref<Date[]>([]);
|
|
49
|
+
const lastScrollTime = ref(new Date());
|
|
50
|
+
const clickedDate = ref<ICalendarDay | undefined>();
|
|
51
|
+
const reMap = () => mapInternalModuleValues(props.isTextInputDate);
|
|
52
|
+
|
|
53
|
+
const { modelValue, calendars, time, today } = useModel(props, emit, reMap);
|
|
54
|
+
const {
|
|
55
|
+
defaultedMultiCalendars,
|
|
56
|
+
defaultedStartTime,
|
|
57
|
+
defaultedRange,
|
|
58
|
+
defaultedConfig,
|
|
59
|
+
defaultedTz,
|
|
60
|
+
propDates,
|
|
61
|
+
defaultedMultiDates,
|
|
62
|
+
} = useDefaults(props);
|
|
63
|
+
const { validateMonthYearInRange, isDisabled, isDateRangeAllowed, checkMinMaxRange } = useValidation(props);
|
|
64
|
+
const { updateTimeValues, getSetDateTime, setTime, assignStartTime, validateTime, disabledTimesConfig } =
|
|
65
|
+
useTimePickerUtils(props, time, modelValue, updateFlow);
|
|
66
|
+
// Get month based on the calendar instance
|
|
67
|
+
const month = computed(
|
|
68
|
+
() =>
|
|
69
|
+
(instance: number): number =>
|
|
70
|
+
calendars.value[instance] ? calendars.value[instance].month : 0,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// Get year based on the calendar instance
|
|
74
|
+
const year = computed(
|
|
75
|
+
() =>
|
|
76
|
+
(instance: number): number =>
|
|
77
|
+
calendars.value[instance] ? calendars.value[instance].year : 0,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const shouldUpdateMonthView = (isAction: boolean) => {
|
|
81
|
+
if (!defaultedConfig.value.keepViewOnOffsetClick || isAction) return true;
|
|
82
|
+
return !clickedDate.value;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Any update for month or year value will go through this function
|
|
86
|
+
const setCalendarMonthYear = (
|
|
87
|
+
instance: number,
|
|
88
|
+
month: number | null,
|
|
89
|
+
year: number | null,
|
|
90
|
+
isAction: boolean = false,
|
|
91
|
+
): void => {
|
|
92
|
+
if (shouldUpdateMonthView(isAction)) {
|
|
93
|
+
if (!calendars.value[instance]) {
|
|
94
|
+
calendars.value[instance] = { month: 0, year: 0 };
|
|
95
|
+
}
|
|
96
|
+
calendars.value[instance].month = isNumNullish(month) ? calendars.value[instance]?.month : month;
|
|
97
|
+
calendars.value[instance].year = isNumNullish(year) ? calendars.value[instance]?.year : year;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const selectOnAutoApply = () => {
|
|
102
|
+
if (props.autoApply) {
|
|
103
|
+
emit('select-date');
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
onMounted(() => {
|
|
108
|
+
if (!props.shadow) {
|
|
109
|
+
if (!modelValue.value) {
|
|
110
|
+
setStartDate();
|
|
111
|
+
if (defaultedStartTime.value) {
|
|
112
|
+
assignStartTime(defaultedStartTime.value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
mapInternalModuleValues(true);
|
|
116
|
+
if (props.focusStartDate && props.startDate) {
|
|
117
|
+
setStartDate();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const isFlowLastStep = computed(() => {
|
|
123
|
+
if (props.flow?.length && !props.partialFlow) {
|
|
124
|
+
return props.flowStep === props.flow.length;
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const autoApply = (): void => {
|
|
130
|
+
if (props.autoApply && isFlowLastStep.value) {
|
|
131
|
+
emit('auto-apply', props.partialFlow ? props.flowStep !== props.flow.length : false);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const mapInternalModuleValues = (fromMount = false): void => {
|
|
136
|
+
if (modelValue.value) {
|
|
137
|
+
if (Array.isArray(modelValue.value)) {
|
|
138
|
+
tempRange.value = modelValue.value;
|
|
139
|
+
return assignExistingModelValueArr(fromMount);
|
|
140
|
+
}
|
|
141
|
+
return assignSingleValue(modelValue.value, fromMount);
|
|
142
|
+
}
|
|
143
|
+
if (defaultedMultiCalendars.value.count && fromMount && !props.startDate)
|
|
144
|
+
return assignMonthAndYear(getDate(), fromMount);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const shouldAssignMultiSolo = () => {
|
|
148
|
+
if (Array.isArray(modelValue.value) && defaultedRange.value.enabled) {
|
|
149
|
+
return getMonth(modelValue.value[0]) === getMonth(modelValue.value[1] ?? modelValue.value[0]);
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Assign month and year values per date
|
|
155
|
+
const assignMonthAndYear = (date = new Date(), fromMount = false): void => {
|
|
156
|
+
if (!defaultedMultiCalendars.value.count || !defaultedMultiCalendars.value.static || fromMount) {
|
|
157
|
+
setCalendarMonthYear(0, getMonth(date), getYear(date));
|
|
158
|
+
}
|
|
159
|
+
if (
|
|
160
|
+
defaultedMultiCalendars.value.count &&
|
|
161
|
+
(!defaultedMultiCalendars.value.solo || !modelValue.value || shouldAssignMultiSolo())
|
|
162
|
+
) {
|
|
163
|
+
for (let i = 1; i < defaultedMultiCalendars.value.count; i++) {
|
|
164
|
+
const prevDate = set(getDate(), { month: month.value(i - 1), year: year.value(i - 1) });
|
|
165
|
+
const nextMonth = add(prevDate, { months: 1 });
|
|
166
|
+
calendars.value[i] = { month: getMonth(nextMonth), year: getYear(nextMonth) };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// Assign singe value
|
|
172
|
+
const assignSingleValue = (date: Date, fromMount: boolean): void => {
|
|
173
|
+
assignMonthAndYear(date);
|
|
174
|
+
setTime('hours', getHours(date));
|
|
175
|
+
setTime('minutes', getMinutes(date));
|
|
176
|
+
setTime('seconds', getSeconds(date));
|
|
177
|
+
if (defaultedMultiCalendars.value.count && fromMount) {
|
|
178
|
+
handleNextMonthYear();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* In case of multi-calendars, check if the range can fit within the view
|
|
184
|
+
* If it can, set focus index to the first date in the range, rest will be auto adjusted
|
|
185
|
+
* In case of solo multi calendars, always take 0 index as reference
|
|
186
|
+
*/
|
|
187
|
+
const getRangeFocusIndex = (dates: Date[]) => {
|
|
188
|
+
if (defaultedMultiCalendars.value.count) {
|
|
189
|
+
if (defaultedMultiCalendars.value.solo) return 0;
|
|
190
|
+
const startMonth = getMonth(dates[0]);
|
|
191
|
+
const endMonth = getMonth(dates[1]);
|
|
192
|
+
const showInTheSameView = Math.abs(endMonth - startMonth) < defaultedMultiCalendars.value.count;
|
|
193
|
+
return showInTheSameView ? 0 : 1;
|
|
194
|
+
}
|
|
195
|
+
return 1;
|
|
196
|
+
};
|
|
197
|
+
// Assign range values
|
|
198
|
+
const assignRangeValue = (dates: Date[], fromMount: boolean) => {
|
|
199
|
+
if (dates[1] && defaultedRange.value.showLastInRange) {
|
|
200
|
+
assignMonthAndYear(dates[getRangeFocusIndex(dates)], fromMount);
|
|
201
|
+
} else {
|
|
202
|
+
assignMonthAndYear(dates[0], fromMount);
|
|
203
|
+
}
|
|
204
|
+
const getValue = (mapper: (date: Date) => number, keys: TimeType): number[] => [
|
|
205
|
+
mapper(dates[0]),
|
|
206
|
+
dates[1] ? mapper(dates[1]) : (time[keys] as number[])[1],
|
|
207
|
+
];
|
|
208
|
+
setTime('hours', getValue(getHours, 'hours'));
|
|
209
|
+
setTime('minutes', getValue(getMinutes, 'minutes'));
|
|
210
|
+
setTime('seconds', getValue(getSeconds, 'seconds'));
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Assign range values, or in case of multiDates, set
|
|
214
|
+
const assignExistingMulti = (dates: Date[], fromMount: boolean) => {
|
|
215
|
+
if ((defaultedRange.value.enabled || props.weekPicker) && !defaultedMultiDates.value.enabled) {
|
|
216
|
+
return assignRangeValue(dates, fromMount);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (defaultedMultiDates.value.enabled && fromMount) {
|
|
220
|
+
const lastEntry = dates[dates.length - 1];
|
|
221
|
+
return assignSingleValue(lastEntry, fromMount);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const assignExistingModelValueArr = (fromMount: boolean) => {
|
|
226
|
+
const dates = modelValue.value as Date[];
|
|
227
|
+
assignExistingMulti(dates, fromMount);
|
|
228
|
+
if (defaultedMultiCalendars.value.count && defaultedMultiCalendars.value.solo) {
|
|
229
|
+
handleNextMonthYear();
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Handle month change on scroll/arrow/swipe
|
|
234
|
+
const autoChangeMonth = (increment: number, instance: number) => {
|
|
235
|
+
const initialDate = set(getDate(), { month: month.value(instance), year: year.value(instance) });
|
|
236
|
+
const date = increment < 0 ? addMonths(initialDate, 1) : subMonths(initialDate, 1);
|
|
237
|
+
if (validateMonthYearInRange(getMonth(date), getYear(date), increment < 0, props.preventMinMaxNavigation)) {
|
|
238
|
+
setCalendarMonthYear(instance, getMonth(date), getYear(date));
|
|
239
|
+
emit('update-month-year', { instance, month: getMonth(date), year: getYear(date) });
|
|
240
|
+
if (defaultedMultiCalendars.value.count && !defaultedMultiCalendars.value.solo) {
|
|
241
|
+
autoChangeMultiCalendars(instance);
|
|
242
|
+
}
|
|
243
|
+
triggerCalendarTransition();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// In multi calendar mode, when the month/year is changed, sync all calendars
|
|
248
|
+
const autoChangeMultiCalendars = (instance: number): void => {
|
|
249
|
+
for (let i = instance - 1; i >= 0; i--) {
|
|
250
|
+
const date = subMonths(set(getDate(), { month: month.value(i + 1), year: year.value(i + 1) }), 1);
|
|
251
|
+
setCalendarMonthYear(i, getMonth(date), getYear(date));
|
|
252
|
+
}
|
|
253
|
+
for (let i = instance + 1; i <= defaultedMultiCalendars.value.count - 1; i++) {
|
|
254
|
+
const date = addMonths(set(getDate(), { month: month.value(i - 1), year: year.value(i - 1) }), 1);
|
|
255
|
+
setCalendarMonthYear(i, getMonth(date), getYear(date));
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Extracted method to map month and year
|
|
261
|
+
*/
|
|
262
|
+
const handleNextMonthYear = (): void => {
|
|
263
|
+
if (Array.isArray(modelValue.value) && modelValue.value.length === 2) {
|
|
264
|
+
const date = getDate(
|
|
265
|
+
getDate(modelValue.value[1] ? modelValue.value[1] : addMonths(modelValue.value[0], 1)),
|
|
266
|
+
);
|
|
267
|
+
const [firstMonth, firstYear] = [getMonth(modelValue.value[0]), getYear(modelValue.value[0])];
|
|
268
|
+
const [secondMonth, secondYear] = [getMonth(modelValue.value[1]), getYear(modelValue.value[1])];
|
|
269
|
+
|
|
270
|
+
if (
|
|
271
|
+
(firstMonth !== secondMonth || (firstMonth === secondMonth && firstYear !== secondYear)) &&
|
|
272
|
+
defaultedMultiCalendars.value.solo
|
|
273
|
+
) {
|
|
274
|
+
setCalendarMonthYear(1, getMonth(date), getYear(date));
|
|
275
|
+
}
|
|
276
|
+
} else if (modelValue.value && !Array.isArray(modelValue.value)) {
|
|
277
|
+
setCalendarMonthYear(0, getMonth(modelValue.value), getYear(modelValue.value));
|
|
278
|
+
assignMonthAndYear(getDate());
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const setStartDate = () => {
|
|
283
|
+
if (props.startDate) {
|
|
284
|
+
setCalendarMonthYear(0, getMonth(getDate(props.startDate)), getYear(getDate(props.startDate)));
|
|
285
|
+
if (defaultedMultiCalendars.value.count) {
|
|
286
|
+
autoChangeMultiCalendars(0);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// Handle mouse scroll
|
|
292
|
+
|
|
293
|
+
const handleScroll = (event: WheelEvent, instance: number): void => {
|
|
294
|
+
if (props.monthChangeOnScroll) {
|
|
295
|
+
const timeDelta: number = new Date().getTime() - lastScrollTime.value.getTime();
|
|
296
|
+
const scrollDistance = Math.abs(event.deltaY);
|
|
297
|
+
let minPause: number = 500;
|
|
298
|
+
if (scrollDistance > 1) minPause = 100;
|
|
299
|
+
if (scrollDistance > 100) minPause = 0;
|
|
300
|
+
if (timeDelta > minPause) {
|
|
301
|
+
lastScrollTime.value = new Date();
|
|
302
|
+
autoChangeMonth(props.monthChangeOnScroll !== 'inverse' ? -event.deltaY : event.deltaY, instance);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// Handle arrow key
|
|
308
|
+
const handleArrow = (arrow: 'left' | 'right', instance: number, vertical = false): void => {
|
|
309
|
+
if (props.monthChangeOnArrows && props.vertical === vertical) {
|
|
310
|
+
handleSwipe(arrow, instance);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// Handle touch swipe
|
|
315
|
+
const handleSwipe = (direction: 'left' | 'right', instance: number): void => {
|
|
316
|
+
autoChangeMonth(direction === 'right' ? -1 : 1, instance);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// Check if the calendar day has a marker
|
|
320
|
+
const getMarker = (date: UnwrapRef<ICalendarDay>): IMarker | undefined => {
|
|
321
|
+
if (propDates.value.markers) {
|
|
322
|
+
return getMapDate(date.value, propDates.value.markers);
|
|
323
|
+
}
|
|
324
|
+
return undefined;
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
const getSixWeeksMode = (firstWeekday: number, gapToEnd: number) => {
|
|
328
|
+
switch (props.sixWeeks === true ? 'append' : props.sixWeeks) {
|
|
329
|
+
case 'prepend':
|
|
330
|
+
return [true, false];
|
|
331
|
+
case 'center':
|
|
332
|
+
return [firstWeekday == 0, true];
|
|
333
|
+
case 'fair':
|
|
334
|
+
return [firstWeekday == 0 || gapToEnd > firstWeekday, true];
|
|
335
|
+
case 'append':
|
|
336
|
+
return [false, false];
|
|
337
|
+
default:
|
|
338
|
+
return [false, false];
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const handleSixWeeks = (
|
|
343
|
+
weeks: ICalendarDate[],
|
|
344
|
+
firstDate: Date,
|
|
345
|
+
lastDate: Date,
|
|
346
|
+
weekStart: WeekStartNum,
|
|
347
|
+
): ICalendarDate[] => {
|
|
348
|
+
if (props.sixWeeks && weeks.length < 6) {
|
|
349
|
+
const diff = 6 - weeks.length;
|
|
350
|
+
|
|
351
|
+
const firstWeekday = (firstDate.getDay() + 7 - weekStart) % 7;
|
|
352
|
+
const lastWeekday = (lastDate.getDay() + 7 - weekStart) % 7;
|
|
353
|
+
const gapToEnd = 6 - lastWeekday;
|
|
354
|
+
const [requiresLeadingWeek, doesAlternate] = getSixWeeksMode(firstWeekday, gapToEnd);
|
|
355
|
+
|
|
356
|
+
for (let i = 1; i <= diff; i++) {
|
|
357
|
+
const addLeadingWeek = doesAlternate ? !!(i % 2) == requiresLeadingWeek : requiresLeadingWeek;
|
|
358
|
+
if (addLeadingWeek) {
|
|
359
|
+
const first = weeks[0].days[0];
|
|
360
|
+
const days = getWeekDays(addDays(first.value, -7), getMonth(firstDate));
|
|
361
|
+
weeks.unshift({ days });
|
|
362
|
+
} else {
|
|
363
|
+
const lastWeek = weeks[weeks.length - 1];
|
|
364
|
+
const last = lastWeek.days[lastWeek.days.length - 1];
|
|
365
|
+
const days = getWeekDays(addDays(last.value, 1), getMonth(firstDate));
|
|
366
|
+
weeks.push({ days });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return weeks;
|
|
371
|
+
};
|
|
372
|
+
// Get 7 days from the provided start date, month is used to check whether the date is from the specified month or in the offset
|
|
373
|
+
const getWeekDays = (startDay: Date, month: number): ICalendarDay[] => {
|
|
374
|
+
const startDate = getDate(startDay);
|
|
375
|
+
const dates = [];
|
|
376
|
+
for (let i = 0; i < 7; i++) {
|
|
377
|
+
const next = addDays(startDate, i);
|
|
378
|
+
const isNext = getMonth(next) !== month;
|
|
379
|
+
dates.push({
|
|
380
|
+
text: props.hideOffsetDates && isNext ? '' : next.getDate(),
|
|
381
|
+
value: next,
|
|
382
|
+
current: !isNext,
|
|
383
|
+
classData: {},
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
return dates;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// Get days for the calendar to be displayed in a table grouped by weeks
|
|
390
|
+
const getCalendarDays = (month: number, year: number): ICalendarDate[] => {
|
|
391
|
+
const weeks: ICalendarDate[] = [];
|
|
392
|
+
const firstDate = new Date(year, month);
|
|
393
|
+
const lastDate = new Date(year, month + 1, 0);
|
|
394
|
+
|
|
395
|
+
const weekStartsOn = props.weekStart as WeekStartNum;
|
|
396
|
+
|
|
397
|
+
const firstDateInCalendar = startOfWeek(firstDate, { weekStartsOn });
|
|
398
|
+
|
|
399
|
+
const addDaysToWeek = (date: Date) => {
|
|
400
|
+
const days = getWeekDays(date, month);
|
|
401
|
+
weeks.push({ days });
|
|
402
|
+
if (
|
|
403
|
+
!weeks[weeks.length - 1].days.some((day) =>
|
|
404
|
+
isDateEqual(resetDateTime(day.value), resetDateTime(lastDate)),
|
|
405
|
+
)
|
|
406
|
+
) {
|
|
407
|
+
const nextDate = addDays(date, 7);
|
|
408
|
+
addDaysToWeek(nextDate);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
addDaysToWeek(firstDateInCalendar);
|
|
412
|
+
|
|
413
|
+
return handleSixWeeks(weeks, firstDate, lastDate, weekStartsOn);
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
// Called on selectDate when the regular single picker is used
|
|
417
|
+
const handleSingleDateSelect = (day: ICalendarDay) => {
|
|
418
|
+
const date = setDateTime(getDate(day.value), time.hours as number, time.minutes as number, getSecondsValue());
|
|
419
|
+
emit('date-update', date);
|
|
420
|
+
if (defaultedMultiDates.value.enabled) {
|
|
421
|
+
handleMultiDatesSelect(date, modelValue, defaultedMultiDates.value.limit);
|
|
422
|
+
} else {
|
|
423
|
+
modelValue.value = date;
|
|
424
|
+
}
|
|
425
|
+
updateFlow();
|
|
426
|
+
nextTick().then(() => {
|
|
427
|
+
autoApply();
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const includesDisabled = (day: Date) => {
|
|
432
|
+
if (!defaultedRange.value.noDisabledRange) return false;
|
|
433
|
+
const daysBetween = getDaysInBetween(tempRange.value[0], day);
|
|
434
|
+
return daysBetween.some((date) => isDisabled(date));
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
// Before range selecting, ensure that modelValue is properly set
|
|
438
|
+
const presetTempRange = () => {
|
|
439
|
+
tempRange.value = modelValue.value ? (modelValue.value as Date[]).slice() : [];
|
|
440
|
+
if (tempRange.value.length === 2 && !(defaultedRange.value.fixedStart || defaultedRange.value.fixedEnd)) {
|
|
441
|
+
tempRange.value = [];
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// Handles auto range selecting
|
|
446
|
+
const handleAutoRange = (day: ICalendarDay, isNext: boolean) => {
|
|
447
|
+
const autoRange = [
|
|
448
|
+
getDate(day.value),
|
|
449
|
+
addDays(getDate(day.value), +(defaultedRange.value.autoRange as number)),
|
|
450
|
+
];
|
|
451
|
+
if (isDateRangeAllowed(autoRange)) {
|
|
452
|
+
if (isNext) {
|
|
453
|
+
handleNextCalendarAutoRange(day.value);
|
|
454
|
+
}
|
|
455
|
+
tempRange.value = autoRange;
|
|
456
|
+
} else {
|
|
457
|
+
emit('invalid-date', day.value);
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* When using next calendar on auto range mode, adjust month and year for both calendars
|
|
463
|
+
*/
|
|
464
|
+
const handleNextCalendarAutoRange = (date: string | Date) => {
|
|
465
|
+
const monthValue = getMonth(getDate(date));
|
|
466
|
+
const yearValue = getYear(getDate(date));
|
|
467
|
+
setCalendarMonthYear(0, monthValue, yearValue);
|
|
468
|
+
if (defaultedMultiCalendars.value.count > 0) {
|
|
469
|
+
for (let i = 1; i < defaultedMultiCalendars.value.count; i++) {
|
|
470
|
+
const next = getNextMonthYear(
|
|
471
|
+
set(getDate(date), { year: year.value(i - 1), month: month.value(i - 1) }),
|
|
472
|
+
);
|
|
473
|
+
setCalendarMonthYear(i, next.month, next.year);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// Handle range with fixed start/end
|
|
479
|
+
const setFixedDateRange = (day: ICalendarDay) => {
|
|
480
|
+
if (
|
|
481
|
+
includesDisabled(day.value) ||
|
|
482
|
+
!checkMinMaxRange(day.value, modelValue.value, defaultedRange.value.fixedStart ? 0 : 1)
|
|
483
|
+
) {
|
|
484
|
+
return emit('invalid-date', day.value);
|
|
485
|
+
}
|
|
486
|
+
tempRange.value = getRangeWithFixedDate(getDate(day.value), modelValue, emit, defaultedRange);
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
// Called on selectDate when range mode is used
|
|
490
|
+
const handleRangeDatesSelect = (day: ICalendarDay, isNext: boolean) => {
|
|
491
|
+
presetTempRange();
|
|
492
|
+
if (defaultedRange.value.autoRange) return handleAutoRange(day, isNext);
|
|
493
|
+
if (defaultedRange.value.fixedStart || defaultedRange.value.fixedEnd) return setFixedDateRange(day);
|
|
494
|
+
if (!tempRange.value[0]) {
|
|
495
|
+
tempRange.value[0] = getDate(day.value);
|
|
496
|
+
emit('range-start', tempRange.value[0]);
|
|
497
|
+
} else if (checkMinMaxRange(getDate(day.value), modelValue.value) && !includesDisabled(day.value)) {
|
|
498
|
+
if (isDateBefore(getDate(day.value), getDate(tempRange.value[0]))) {
|
|
499
|
+
tempRange.value.unshift(getDate(day.value));
|
|
500
|
+
emit('range-end', tempRange.value[0]);
|
|
501
|
+
} else {
|
|
502
|
+
tempRange.value[1] = getDate(day.value);
|
|
503
|
+
emit('range-end', tempRange.value[1]);
|
|
504
|
+
}
|
|
505
|
+
} else {
|
|
506
|
+
if (props.autoApply) {
|
|
507
|
+
emit('auto-apply-invalid', day.value);
|
|
508
|
+
}
|
|
509
|
+
emit('invalid-date', day.value);
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
// Check if seconds are enabled, and return proper value
|
|
514
|
+
const getSecondsValue = (getFirst = true): number => {
|
|
515
|
+
if (props.enableSeconds) {
|
|
516
|
+
if (Array.isArray(time.seconds)) {
|
|
517
|
+
return getFirst ? time.seconds[0] : time.seconds[1];
|
|
518
|
+
}
|
|
519
|
+
return time.seconds;
|
|
520
|
+
}
|
|
521
|
+
return 0;
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// Assign time to a temp range item
|
|
525
|
+
const assignTime = (index: number) => {
|
|
526
|
+
tempRange.value[index] = setDateTime(
|
|
527
|
+
tempRange.value[index],
|
|
528
|
+
(time.hours as number[])[index],
|
|
529
|
+
(time.minutes as number[])[index],
|
|
530
|
+
getSecondsValue(index !== 1),
|
|
531
|
+
);
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
const validateRangeAfterTimeSet = () => {
|
|
535
|
+
if (tempRange.value[0] && tempRange.value[1]) {
|
|
536
|
+
if (+tempRange.value?.[0] > +tempRange.value?.[1]) {
|
|
537
|
+
tempRange.value.reverse();
|
|
538
|
+
emit('range-start', tempRange.value[0]);
|
|
539
|
+
emit('range-end', tempRange.value[1]);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// After range date is select, ensure that proper times are set and assign to modelValue
|
|
545
|
+
const postRangeSelect = () => {
|
|
546
|
+
if (tempRange.value.length) {
|
|
547
|
+
if (tempRange.value[0] && !tempRange.value[1]) {
|
|
548
|
+
assignTime(0);
|
|
549
|
+
} else {
|
|
550
|
+
assignTime(0);
|
|
551
|
+
assignTime(1);
|
|
552
|
+
updateFlow();
|
|
553
|
+
}
|
|
554
|
+
validateRangeAfterTimeSet();
|
|
555
|
+
modelValue.value = tempRange.value.slice();
|
|
556
|
+
|
|
557
|
+
checkRangeAutoApply(tempRange.value, emit, props.autoApply, props.modelAuto);
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Called when the date in the calendar is clicked
|
|
563
|
+
* Do a necessary formatting and assign value to internal
|
|
564
|
+
*/
|
|
565
|
+
const selectDate = (day: ICalendarDay, isNext = false): void => {
|
|
566
|
+
if (isDisabled(day.value) || (!day.current && props.hideOffsetDates)) return emit('invalid-date', day.value);
|
|
567
|
+
clickedDate.value = JSON.parse(JSON.stringify(day));
|
|
568
|
+
|
|
569
|
+
if (!defaultedRange.value.enabled) return handleSingleDateSelect(day);
|
|
570
|
+
|
|
571
|
+
if (isNumberArray(time.hours) && isNumberArray(time.minutes) && !defaultedMultiDates.value.enabled) {
|
|
572
|
+
handleRangeDatesSelect(day, isNext);
|
|
573
|
+
postRangeSelect();
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
// Handles selection of month/year
|
|
578
|
+
const updateMonthYear = (instance: number, val: { month: number; year: number; fromNav?: boolean }): void => {
|
|
579
|
+
setCalendarMonthYear(instance, val.month, val.year, true);
|
|
580
|
+
|
|
581
|
+
if (defaultedMultiCalendars.value.count && !defaultedMultiCalendars.value.solo) {
|
|
582
|
+
autoChangeMultiCalendars(instance);
|
|
583
|
+
}
|
|
584
|
+
emit('update-month-year', { instance, month: val.month, year: val.year });
|
|
585
|
+
triggerCalendarTransition(defaultedMultiCalendars.value.solo ? instance : undefined);
|
|
586
|
+
|
|
587
|
+
const flowActive = props.flow?.length ? props.flow[props.flowStep] : undefined;
|
|
588
|
+
if (!val.fromNav && (flowActive === FlowStep.month || flowActive === FlowStep.year)) {
|
|
589
|
+
updateFlow();
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
// Called when the preset date is clicked
|
|
594
|
+
const presetDate = (value: Date[] | string[] | Date | string, noTz?: boolean): void => {
|
|
595
|
+
setPresetDate({
|
|
596
|
+
value,
|
|
597
|
+
modelValue,
|
|
598
|
+
range: defaultedRange.value.enabled,
|
|
599
|
+
timezone: noTz ? undefined : defaultedTz.value.timezone,
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
selectOnAutoApply();
|
|
603
|
+
if (props.multiCalendars) {
|
|
604
|
+
nextTick().then(() => mapInternalModuleValues(true));
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
// Select current date on now button
|
|
609
|
+
const selectCurrentDate = (): void => {
|
|
610
|
+
const dateInTz = dateToTimezoneSafe(getDate(), defaultedTz.value);
|
|
611
|
+
if (!defaultedRange.value.enabled) {
|
|
612
|
+
modelValue.value = dateInTz;
|
|
613
|
+
} else if (modelValue.value && Array.isArray(modelValue.value) && modelValue.value[0]) {
|
|
614
|
+
modelValue.value = isDateBefore(dateInTz, modelValue.value[0])
|
|
615
|
+
? [dateInTz, modelValue.value[0]]
|
|
616
|
+
: [modelValue.value[0], dateInTz];
|
|
617
|
+
} else {
|
|
618
|
+
modelValue.value = [dateInTz];
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
selectOnAutoApply();
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
const handleTimeUpdate = () => {
|
|
625
|
+
if (Array.isArray(modelValue.value)) {
|
|
626
|
+
if (defaultedMultiDates.value.enabled) {
|
|
627
|
+
const lastEntry = multiDatesLast();
|
|
628
|
+
modelValue.value[modelValue.value.length - 1] = getSetDateTime(lastEntry as Date);
|
|
629
|
+
} else {
|
|
630
|
+
modelValue.value = modelValue.value.map((date, i) => {
|
|
631
|
+
if (date) return getSetDateTime(date, i);
|
|
632
|
+
return date;
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
} else {
|
|
636
|
+
modelValue.value = getSetDateTime(modelValue.value);
|
|
637
|
+
}
|
|
638
|
+
emit('time-update');
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
// Get last date in the multi dates arr
|
|
642
|
+
const multiDatesLast = (): Date | null => {
|
|
643
|
+
if (Array.isArray(modelValue.value) && modelValue.value.length) {
|
|
644
|
+
return modelValue.value[modelValue.value.length - 1];
|
|
645
|
+
}
|
|
646
|
+
return null;
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
const updateTime = (value: number | number[], isHours = true, isSeconds = false) => {
|
|
650
|
+
updateTimeValues(value, isHours, isSeconds, handleTimeUpdate);
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
return {
|
|
654
|
+
calendars,
|
|
655
|
+
modelValue,
|
|
656
|
+
month,
|
|
657
|
+
year,
|
|
658
|
+
time,
|
|
659
|
+
disabledTimesConfig,
|
|
660
|
+
today,
|
|
661
|
+
validateTime,
|
|
662
|
+
getCalendarDays,
|
|
663
|
+
getMarker,
|
|
664
|
+
handleScroll,
|
|
665
|
+
handleSwipe,
|
|
666
|
+
handleArrow,
|
|
667
|
+
selectDate,
|
|
668
|
+
updateMonthYear,
|
|
669
|
+
presetDate,
|
|
670
|
+
selectCurrentDate,
|
|
671
|
+
updateTime,
|
|
672
|
+
assignMonthAndYear,
|
|
673
|
+
};
|
|
674
|
+
};
|