design-system-next 2.11.9 → 2.11.15
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/design-system-next.es.js +7921 -6733
- package/dist/design-system-next.es.js.gz +0 -0
- package/dist/design-system-next.umd.js +12 -12
- package/dist/design-system-next.umd.js.gz +0 -0
- package/dist/main.css +1 -1
- package/dist/main.css.gz +0 -0
- package/dist/package.json.d.ts +1 -1
- package/package.json +1 -1
- package/src/assets/styles/tailwind.css +20 -0
- package/src/components/calendar-cell/use-calendar-cell.ts +1 -1
- package/src/components/date-picker/date-range-picker/date-range-picker.ts +193 -0
- package/src/components/date-picker/date-range-picker/date-range-picker.vue +411 -0
- package/src/components/date-picker/date-range-picker/use-date-range-picker.ts +957 -0
- package/src/components/list/ladderized-list/use-ladderized-list.ts +92 -9
- package/src/components/list/list.ts +1 -1
- package/src/components/list/list.vue +81 -69
- package/src/components/list/use-list.ts +213 -77
- package/src/components/select/select-ladderized/select-ladderized.ts +2 -0
- package/src/components/select/select-ladderized/select-ladderized.vue +2 -2
- package/src/components/select/select-ladderized/use-select-ladderized.ts +53 -3
- package/src/components/select/select-multiple/select-multiple.ts +1 -1
- package/src/components/sidenav/sidenav.vue +22 -18
- package/src/components/sidenav/use-sidenav.ts +1 -1
- package/src/components/tabs/use-tabs.ts +16 -2
|
@@ -0,0 +1,957 @@
|
|
|
1
|
+
import { onClickOutside, useVModel } from '@vueuse/core';
|
|
2
|
+
import { computed, ComputedRef, nextTick, onMounted, ref, SetupContext, toRefs, watch, useSlots } from 'vue';
|
|
3
|
+
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
|
+
import isBetween from 'dayjs/plugin/isBetween';
|
|
6
|
+
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
|
|
7
|
+
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
|
|
8
|
+
|
|
9
|
+
import classNames from 'classnames';
|
|
10
|
+
|
|
11
|
+
import type { DateRangePickerEmitTypes, DateRangePickerPropTypes } from './date-range-picker';
|
|
12
|
+
import { PLACEMENTS_TYPES } from './date-range-picker';
|
|
13
|
+
|
|
14
|
+
dayjs.extend(isSameOrBefore);
|
|
15
|
+
dayjs.extend(isSameOrAfter);
|
|
16
|
+
dayjs.extend(isBetween);
|
|
17
|
+
|
|
18
|
+
interface DateRangePickerClasses {
|
|
19
|
+
labelClasses: string;
|
|
20
|
+
dateRangePickerBaseInputClasses: string;
|
|
21
|
+
dateRangePickerInputClasses: string;
|
|
22
|
+
dateRangePickerInputHelperClasses: string;
|
|
23
|
+
calendarTabItemsBaseClasses: string;
|
|
24
|
+
monthsTabItemsBaseClasses: string;
|
|
25
|
+
yearsTabItemsBaseClasses: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface MonthsList {
|
|
29
|
+
text: string;
|
|
30
|
+
fullText: string;
|
|
31
|
+
monthValue: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type DayAbbreviation = 'su' | 'mo' | 'tu' | 'we' | 'th' | 'fr' | 'sa';
|
|
35
|
+
|
|
36
|
+
export const useDateRangePicker = (props: DateRangePickerPropTypes, emit: SetupContext<DateRangePickerEmitTypes>['emit']) => {
|
|
37
|
+
const { active, disabled, readonly, error, currentYear, minMaxYear, restDays, disabledDates, format } = toRefs(props);
|
|
38
|
+
const slots = useSlots();
|
|
39
|
+
|
|
40
|
+
const modelValue = useVModel(props, 'modelValue', emit);
|
|
41
|
+
|
|
42
|
+
const dateRangePickerClasses: ComputedRef<DateRangePickerClasses> = computed(() => {
|
|
43
|
+
const labelClasses = classNames('spr-body-sm-regular spr-text-color-strong spr-block', {
|
|
44
|
+
'spr-text-color-on-fill-disabled': disabled.value,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const dateRangePickerBaseInputClasses = classNames(
|
|
48
|
+
'spr-flex spr-justify-between spr-items-center spr-gap-6 spr-rounded-lg spr-bg-white-50 spr-min-w-[180px] spr-py-1.5 spr-px-3',
|
|
49
|
+
{
|
|
50
|
+
// Normal State
|
|
51
|
+
'spr-border spr-border-solid spr-border-mushroom-200 focus:spr-border-kangkong-700':
|
|
52
|
+
(!error.value && !disabled.value && !active.value && !datePopperState.value) || readonly.value,
|
|
53
|
+
|
|
54
|
+
// Active State
|
|
55
|
+
'spr-border spr-border-solid spr-border-kangkong-700 spr-border-[1.5px] spr-border-solid':
|
|
56
|
+
(active.value || datePopperState.value === true) && !readonly.value,
|
|
57
|
+
|
|
58
|
+
// Error State
|
|
59
|
+
'spr-border spr-border-solid spr-border-tomato-600 focus:spr-border-tomato-600': error.value,
|
|
60
|
+
|
|
61
|
+
// Disabled State
|
|
62
|
+
'spr-background-color-disabled spr-border-white-100 focus:spr-border-white-100 spr-cursor-not-allowed !spr-text-white-400':
|
|
63
|
+
disabled.value,
|
|
64
|
+
|
|
65
|
+
// Readonly State
|
|
66
|
+
'spr-cursor-default': readonly.value,
|
|
67
|
+
},
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const dateRangePickerInputClasses = classNames(
|
|
71
|
+
'spr-h-full spr-border-none spr-bg-transparent spr-outline-none',
|
|
72
|
+
'spr-font-size-200',
|
|
73
|
+
'placeholder:spr-text-color-weak',
|
|
74
|
+
{
|
|
75
|
+
'spr-text-color-strong': !disabled.value && !readonly.value,
|
|
76
|
+
'spr-text-color-on-fill-disabled': disabled.value || readonly.value,
|
|
77
|
+
'spr-cursor-not-allowed': disabled.value,
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const dateRangePickerInputHelperClasses = classNames(
|
|
82
|
+
'spr-body-sm-regular',
|
|
83
|
+
'spr-flex spr-items-center spr-gap-size-spacing-5xs',
|
|
84
|
+
'spr-mt-size-spacing-4xs',
|
|
85
|
+
{
|
|
86
|
+
'spr-text-color-danger-base': error.value,
|
|
87
|
+
'spr-text-color-supporting': !error.value,
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const calendarTabItemsBaseClasses = classNames(
|
|
92
|
+
'spr-relative spr-box-border spr-flex spr-h-[40px] spr-items-center spr-justify-center spr-p-2',
|
|
93
|
+
'spr-transition spr-duration-150 spr-ease-in-out',
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const monthsTabItemsBaseClasses = classNames(
|
|
97
|
+
'spr-subheading-xs spr-relative spr-flex spr-cursor-pointer spr-items-center spr-justify-center spr-rounded-lg spr-p-4',
|
|
98
|
+
'spr-border spr-border-solid',
|
|
99
|
+
'spr-transition spr-duration-150 spr-ease-in-out',
|
|
100
|
+
'active:spr-scale-95',
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const yearsTabItemsBaseClasses = classNames(
|
|
104
|
+
'spr-subheading-xs spr-relative spr-flex spr-cursor-pointer spr-items-center spr-justify-center spr-rounded-lg spr-p-4',
|
|
105
|
+
'spr-border spr-border-solid',
|
|
106
|
+
'spr-transition spr-duration-150 spr-ease-in-out',
|
|
107
|
+
'active:spr-scale-95',
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
labelClasses,
|
|
112
|
+
dateRangePickerBaseInputClasses,
|
|
113
|
+
dateRangePickerInputClasses,
|
|
114
|
+
dateRangePickerInputHelperClasses,
|
|
115
|
+
calendarTabItemsBaseClasses,
|
|
116
|
+
monthsTabItemsBaseClasses,
|
|
117
|
+
yearsTabItemsBaseClasses,
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const dateRangePickerRef = ref<HTMLInputElement | null>(null);
|
|
122
|
+
const startMonthInputRef = ref<HTMLInputElement | null>(null);
|
|
123
|
+
const startDateInputRef = ref<HTMLInputElement | null>(null);
|
|
124
|
+
const startYearInputRef = ref<HTMLInputElement | null>(null);
|
|
125
|
+
const endMonthInputRef = ref<HTMLInputElement | null>(null);
|
|
126
|
+
const endDateInputRef = ref<HTMLInputElement | null>(null);
|
|
127
|
+
const endYearInputRef = ref<HTMLInputElement | null>(null);
|
|
128
|
+
|
|
129
|
+
// Refs for container elements
|
|
130
|
+
const startDateContainerRef = ref<HTMLElement | null>(null);
|
|
131
|
+
const endDateContainerRef = ref<HTMLElement | null>(null);
|
|
132
|
+
|
|
133
|
+
// Track which input was clicked
|
|
134
|
+
const activeInputRef = ref<HTMLElement | null>(null);
|
|
135
|
+
const clickedInputType = ref<'start' | 'end'>('start');
|
|
136
|
+
|
|
137
|
+
const datePopperState = ref<boolean>(false);
|
|
138
|
+
const currentTab = ref<string>('tab-calendar');
|
|
139
|
+
const currentDate = ref(dayjs());
|
|
140
|
+
const selectionMode = ref<'start' | 'end'>('start');
|
|
141
|
+
|
|
142
|
+
const daysOfWeek = ref(
|
|
143
|
+
Array.from({ length: 7 }, (_, i) => ({
|
|
144
|
+
text: dayjs().day(i).format('dd'),
|
|
145
|
+
fullText: dayjs().day(i).format('dddd'),
|
|
146
|
+
dayValue: i,
|
|
147
|
+
})),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const monthsList = ref<MonthsList[]>(
|
|
151
|
+
Array.from({ length: 12 }, (_, i) => ({
|
|
152
|
+
text: dayjs().month(i).format('MMM'),
|
|
153
|
+
fullText: dayjs().month(i).format('MMMM'),
|
|
154
|
+
monthValue: i,
|
|
155
|
+
}))
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Start date inputs
|
|
159
|
+
const startMonthInput = ref<string>('');
|
|
160
|
+
const startDateInput = ref<string>('');
|
|
161
|
+
const startYearInput = ref<string>('');
|
|
162
|
+
|
|
163
|
+
// End date inputs
|
|
164
|
+
const endMonthInput = ref<string>('');
|
|
165
|
+
const endDateInput = ref<string>('');
|
|
166
|
+
const endYearInput = ref<string>('');
|
|
167
|
+
|
|
168
|
+
const dateRangePickerErrors = ref<{ title: string; message: string }[]>([]);
|
|
169
|
+
|
|
170
|
+
// #region - Calendar Tab
|
|
171
|
+
const calendarTabPageData = ref({
|
|
172
|
+
selectedMonth: dayjs().month(),
|
|
173
|
+
selectedYear: Number(currentYear.value),
|
|
174
|
+
calendarDays: [] as Array<{ date: dayjs.Dayjs; inactive: boolean }>,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const calendarTabIsMinMonth = computed(() =>
|
|
178
|
+
dayjs()
|
|
179
|
+
.year(calendarTabPageData.value.selectedYear)
|
|
180
|
+
.month(calendarTabPageData.value.selectedMonth)
|
|
181
|
+
.isSame(dayjs().year(minMaxYear.value.min).month(0), 'month'),
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const calendarTabIsMaxMonth = computed(() =>
|
|
185
|
+
dayjs()
|
|
186
|
+
.year(calendarTabPageData.value.selectedYear)
|
|
187
|
+
.month(calendarTabPageData.value.selectedMonth)
|
|
188
|
+
.isSame(dayjs().year(minMaxYear.value.max).month(11), 'month'),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const calendarTabUpdateCalendar = () => {
|
|
192
|
+
const firstDay = dayjs()
|
|
193
|
+
.year(calendarTabPageData.value.selectedYear)
|
|
194
|
+
.month(calendarTabPageData.value.selectedMonth)
|
|
195
|
+
.startOf('month')
|
|
196
|
+
.day();
|
|
197
|
+
|
|
198
|
+
const lastDate = dayjs()
|
|
199
|
+
.year(calendarTabPageData.value.selectedYear)
|
|
200
|
+
.month(calendarTabPageData.value.selectedMonth)
|
|
201
|
+
.endOf('month')
|
|
202
|
+
.date();
|
|
203
|
+
|
|
204
|
+
const prevMonthDays = firstDay;
|
|
205
|
+
const totalDays = prevMonthDays + lastDate;
|
|
206
|
+
const nextMonthDays = totalDays % 7 === 0 ? 0 : 7 - (totalDays % 7);
|
|
207
|
+
|
|
208
|
+
const calendar = [];
|
|
209
|
+
|
|
210
|
+
// Previous month days
|
|
211
|
+
for (let index = prevMonthDays; index > 0; index--) {
|
|
212
|
+
const date = dayjs()
|
|
213
|
+
.year(calendarTabPageData.value.selectedYear)
|
|
214
|
+
.month(calendarTabPageData.value.selectedMonth)
|
|
215
|
+
.date(-index + 1);
|
|
216
|
+
|
|
217
|
+
calendar.push({ date, inactive: true });
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Current month days
|
|
221
|
+
for (let index = 1; index <= lastDate; index++) {
|
|
222
|
+
const date = dayjs()
|
|
223
|
+
.year(calendarTabPageData.value.selectedYear)
|
|
224
|
+
.month(calendarTabPageData.value.selectedMonth)
|
|
225
|
+
.date(index);
|
|
226
|
+
|
|
227
|
+
calendar.push({ date, inactive: false });
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Next month days
|
|
231
|
+
for (let index = 1; index <= nextMonthDays; index++) {
|
|
232
|
+
const date = dayjs()
|
|
233
|
+
.year(calendarTabPageData.value.selectedYear)
|
|
234
|
+
.month(calendarTabPageData.value.selectedMonth)
|
|
235
|
+
.date(lastDate + index);
|
|
236
|
+
|
|
237
|
+
calendar.push({ date, inactive: true });
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
calendarTabPageData.value.calendarDays = calendar;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const calendarTabPrevMonth = () => {
|
|
244
|
+
if (calendarTabPageData.value.selectedMonth === 0) {
|
|
245
|
+
calendarTabPageData.value.selectedMonth = 11;
|
|
246
|
+
calendarTabPageData.value.selectedYear--;
|
|
247
|
+
} else {
|
|
248
|
+
calendarTabPageData.value.selectedMonth--;
|
|
249
|
+
}
|
|
250
|
+
calendarTabUpdateCalendar();
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const calendarTabNextMonth = () => {
|
|
254
|
+
if (calendarTabPageData.value.selectedMonth === 11) {
|
|
255
|
+
calendarTabPageData.value.selectedMonth = 0;
|
|
256
|
+
calendarTabPageData.value.selectedYear++;
|
|
257
|
+
} else {
|
|
258
|
+
calendarTabPageData.value.selectedMonth++;
|
|
259
|
+
}
|
|
260
|
+
calendarTabUpdateCalendar();
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const calendarTabIsRestDay = (day: { date: dayjs.Dayjs; inactive: boolean }) => {
|
|
264
|
+
if (restDays.value.length === 0) return false;
|
|
265
|
+
// Use 'dd' format returns e.g. 'Su', 'Mo', etc. We need to map to 'su', 'mo', etc.
|
|
266
|
+
const dayOfWeek = day.date.format('dd').toLowerCase() as DayAbbreviation;
|
|
267
|
+
return restDays.value.includes(dayOfWeek);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const calendarTabIsTodayIndicator = (day: { date: dayjs.Dayjs }) => {
|
|
271
|
+
return day.date.isSame(dayjs(), 'day');
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const calendarTabIsActiveMonthDates = (day: { date: dayjs.Dayjs; inactive: boolean }) => {
|
|
275
|
+
return !day.inactive;
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const calendarTabIsInactiveMonthDates = (day: { date: dayjs.Dayjs; inactive: boolean }) => {
|
|
279
|
+
return day.inactive;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const calendarTabIsSelectedDate = (day: { date: dayjs.Dayjs; inactive: boolean }) => {
|
|
283
|
+
|
|
284
|
+
const startDate = dayjs(modelValue.value.startDate).format('MM-DD-YYYY');
|
|
285
|
+
const endDate = dayjs(modelValue.value.endDate).format('MM-DD-YYYY');
|
|
286
|
+
|
|
287
|
+
const dayDate = day.date.format('MM-DD-YYYY');
|
|
288
|
+
// If only start date is selected, highlight it
|
|
289
|
+
if (startDate && !endDate) {
|
|
290
|
+
return dayDate === startDate;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// If both dates are selected, highlight start and end
|
|
294
|
+
if (startDate && endDate) {
|
|
295
|
+
return dayDate === startDate || dayDate === endDate;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return false;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const calendarTabIsInRange = (day: { date: dayjs.Dayjs; inactive: boolean }) => {
|
|
302
|
+
const startDate = modelValue.value.startDate;
|
|
303
|
+
const endDate = modelValue.value.endDate;
|
|
304
|
+
|
|
305
|
+
// Only show range when both dates are selected
|
|
306
|
+
if (!startDate || !endDate) return false;
|
|
307
|
+
|
|
308
|
+
const dayDate = day.date;
|
|
309
|
+
const start = dayjs(startDate, 'MM-DD-YYYY');
|
|
310
|
+
const end = dayjs(endDate, 'MM-DD-YYYY');
|
|
311
|
+
|
|
312
|
+
return dayDate.isAfter(start, 'day') && dayDate.isBefore(end, 'day');
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const calendarTabIsUnSelectedDate = (day: { date: dayjs.Dayjs }) => {
|
|
316
|
+
const startDate = modelValue.value.startDate;
|
|
317
|
+
const endDate = modelValue.value.endDate;
|
|
318
|
+
|
|
319
|
+
if (!startDate || !endDate) return true;
|
|
320
|
+
|
|
321
|
+
const dayDate = day.date.format('MM-DD-YYYY');
|
|
322
|
+
return dayDate !== startDate && dayDate !== endDate;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const calendarTabIsDateIsDisabled = (day: { date: dayjs.Dayjs }) => {
|
|
326
|
+
return (
|
|
327
|
+
calendarTabIsDateDisabledFromTo(day) ||
|
|
328
|
+
calendarTabIsDateDisabledPastDate(day) ||
|
|
329
|
+
calendarTabIsDateDisabledFutureDate(day) ||
|
|
330
|
+
calendarTabIsDateDisabledSelectedDates(day) ||
|
|
331
|
+
calendarTabIsDateDisabledWeekends(day) ||
|
|
332
|
+
calendarTabIsDateDisabledWeekdays(day) ||
|
|
333
|
+
calendarTabIsDateDisabledSelectedDays(day)
|
|
334
|
+
);
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const calendarTabIsDateDisabledFromTo = (day: { date: dayjs.Dayjs }) => {
|
|
338
|
+
if (!safeDisabledDates.value?.from || !safeDisabledDates.value?.to) return false;
|
|
339
|
+
const dayDate = day.date;
|
|
340
|
+
const fromDate = dayjs(safeDisabledDates.value.from, 'MM-DD-YYYY');
|
|
341
|
+
const toDate = dayjs(safeDisabledDates.value.to, 'MM-DD-YYYY');
|
|
342
|
+
return dayDate.isBetween(fromDate, toDate, 'day', '[]');
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const calendarTabIsDateDisabledPastDate = (day: { date: dayjs.Dayjs }) => {
|
|
346
|
+
if (!safeDisabledDates.value?.pastDates) return false;
|
|
347
|
+
const dayDate = day.date;
|
|
348
|
+
const currentDate = dayjs();
|
|
349
|
+
|
|
350
|
+
if (typeof safeDisabledDates.value.pastDates === 'string') {
|
|
351
|
+
const pastDate = dayjs(safeDisabledDates.value.pastDates, 'MM-DD-YYYY');
|
|
352
|
+
return dayDate.isBefore(pastDate, 'day');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return dayDate.isBefore(currentDate, 'day');
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const calendarTabIsDateDisabledFutureDate = (day: { date: dayjs.Dayjs }) => {
|
|
359
|
+
if (!safeDisabledDates.value?.futureDates) return false;
|
|
360
|
+
const dayDate = day.date;
|
|
361
|
+
const currentDate = dayjs();
|
|
362
|
+
|
|
363
|
+
if (typeof safeDisabledDates.value.futureDates === 'string') {
|
|
364
|
+
const futureDate = dayjs(safeDisabledDates.value.futureDates, 'MM-DD-YYYY');
|
|
365
|
+
return dayDate.isAfter(futureDate, 'day');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return dayDate.isAfter(currentDate, 'day');
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
const calendarTabIsDateDisabledSelectedDates = (day: { date: dayjs.Dayjs }) => {
|
|
372
|
+
if (!safeDisabledDates.value?.selectedDates) return false;
|
|
373
|
+
const dayDate = day.date.format('MM-DD-YYYY');
|
|
374
|
+
return safeDisabledDates.value.selectedDates.includes(dayDate);
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const calendarTabIsDateDisabledWeekends = (day: { date: dayjs.Dayjs }) => {
|
|
378
|
+
if (!safeDisabledDates.value?.weekends) return false;
|
|
379
|
+
const dayOfWeek = day.date.day();
|
|
380
|
+
return dayOfWeek === 0 || dayOfWeek === 6;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const calendarTabIsDateDisabledWeekdays = (day: { date: dayjs.Dayjs }) => {
|
|
384
|
+
if (!safeDisabledDates.value?.weekdays) return false;
|
|
385
|
+
const dayOfWeek = day.date.day();
|
|
386
|
+
return dayOfWeek >= 1 && dayOfWeek <= 5;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
const calendarTabIsDateDisabledSelectedDays = (day: { date: dayjs.Dayjs }) => {
|
|
390
|
+
if (!safeDisabledDates.value?.selectedDays) return false;
|
|
391
|
+
const dayOfWeek = day.date.format('dd').toLowerCase() as DayAbbreviation;
|
|
392
|
+
return safeDisabledDates.value.selectedDays.includes(dayOfWeek);
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
// Update calendarTabHandleDateInput to use format.value
|
|
396
|
+
const calendarTabHandleDateInput = (day: { date: dayjs.Dayjs }) => {
|
|
397
|
+
if (calendarTabIsDateIsDisabled(day)) return;
|
|
398
|
+
|
|
399
|
+
const selectedDate = dayjs(day.date).format(format.value);
|
|
400
|
+
|
|
401
|
+
// If no start date is selected, set it as start date
|
|
402
|
+
if (!modelValue.value.startDate) {
|
|
403
|
+
modelValue.value = {
|
|
404
|
+
...modelValue.value,
|
|
405
|
+
startDate: selectedDate,
|
|
406
|
+
};
|
|
407
|
+
selectionMode.value = 'end';
|
|
408
|
+
}
|
|
409
|
+
// If start date is selected but no end date, set it as end date
|
|
410
|
+
else if (!modelValue.value.endDate) {
|
|
411
|
+
// If selected date is before start date, swap them
|
|
412
|
+
if (dayjs(selectedDate, format.value).isBefore(dayjs(modelValue.value.startDate, format.value))) {
|
|
413
|
+
modelValue.value = {
|
|
414
|
+
startDate: selectedDate,
|
|
415
|
+
endDate: modelValue.value.startDate,
|
|
416
|
+
};
|
|
417
|
+
} else {
|
|
418
|
+
modelValue.value = {
|
|
419
|
+
...modelValue.value,
|
|
420
|
+
endDate: selectedDate,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
selectionMode.value = 'start';
|
|
424
|
+
datePopperState.value = false;
|
|
425
|
+
}
|
|
426
|
+
// If both dates are selected, start a new selection
|
|
427
|
+
else {
|
|
428
|
+
modelValue.value = {
|
|
429
|
+
startDate: selectedDate,
|
|
430
|
+
endDate: '',
|
|
431
|
+
};
|
|
432
|
+
selectionMode.value = 'end';
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
updateInputFields();
|
|
436
|
+
emitRangeChange();
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// #region - Month Tab
|
|
440
|
+
const monthTabHandleSelectedMonth = (selectedMonth: { text: string; fullText: string; monthValue: number }) => {
|
|
441
|
+
calendarTabPageData.value.selectedMonth = selectedMonth.monthValue;
|
|
442
|
+
calendarTabUpdateCalendar();
|
|
443
|
+
currentTab.value = 'tab-calendar';
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
// #region - Year Tab
|
|
447
|
+
const yearsArray = Array.from(
|
|
448
|
+
{ length: minMaxYear.value.max - minMaxYear.value.min + 1 },
|
|
449
|
+
(_, index) => minMaxYear.value.min + index,
|
|
450
|
+
).filter((year) => year <= minMaxYear.value.max && year >= minMaxYear.value.min);
|
|
451
|
+
|
|
452
|
+
const yearTabPageData = ref({
|
|
453
|
+
currentPage: 0,
|
|
454
|
+
itemsPerPage: 12,
|
|
455
|
+
yearsArray,
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
const yearTabCurrentYearPage = computed(() => {
|
|
459
|
+
const start = yearTabPageData.value.currentPage * yearTabPageData.value.itemsPerPage;
|
|
460
|
+
const remainingItems = yearTabPageData.value.yearsArray.slice(start);
|
|
461
|
+
return remainingItems.length < yearTabPageData.value.itemsPerPage
|
|
462
|
+
? remainingItems
|
|
463
|
+
: yearTabPageData.value.yearsArray.slice(start, start + yearTabPageData.value.itemsPerPage);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
const yearsTabSetCurrentPageYear = () => {
|
|
467
|
+
const currentYearIndex = yearTabPageData.value.yearsArray.indexOf(calendarTabPageData.value.selectedYear);
|
|
468
|
+
if (currentYearIndex !== -1) {
|
|
469
|
+
yearTabPageData.value.currentPage = Math.floor(currentYearIndex / yearTabPageData.value.itemsPerPage);
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const yearTabGoToPreviousPage = () => {
|
|
474
|
+
if (yearTabPageData.value.currentPage > 0) {
|
|
475
|
+
yearTabPageData.value.currentPage--;
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const yearTabGoToNextPage = () => {
|
|
480
|
+
if ((yearTabPageData.value.currentPage + 1) * yearTabPageData.value.itemsPerPage < yearTabPageData.value.yearsArray.length) {
|
|
481
|
+
yearTabPageData.value.currentPage++;
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
const yearTabIsPreviousButtonDisabled = computed(() => {
|
|
486
|
+
return yearTabPageData.value.currentPage === 0;
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
const yearTabIsNextButtonDisabled = computed(() => {
|
|
490
|
+
return (
|
|
491
|
+
(yearTabPageData.value.currentPage + 1) * yearTabPageData.value.itemsPerPage >= yearTabPageData.value.yearsArray.length
|
|
492
|
+
);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
const yearTabHandleSelectedYear = (selectedYear: string) => {
|
|
496
|
+
calendarTabPageData.value.selectedYear = Number(selectedYear);
|
|
497
|
+
// Fill the correct year input based on selectionMode
|
|
498
|
+
if (selectionMode.value === 'start') {
|
|
499
|
+
startYearInput.value = selectedYear;
|
|
500
|
+
} else {
|
|
501
|
+
endYearInput.value = selectedYear;
|
|
502
|
+
}
|
|
503
|
+
calendarTabUpdateCalendar();
|
|
504
|
+
currentTab.value = 'tab-calendar';
|
|
505
|
+
yearsTabSetCurrentPageYear();
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
// #region - Input Handling
|
|
509
|
+
// Update setWarningPropsValue to use format.value for error messages
|
|
510
|
+
const setWarningPropsValue = (type: 'startDate' | 'endDate' | 'range' | 'year') => {
|
|
511
|
+
const warningProps = {
|
|
512
|
+
startDate: {
|
|
513
|
+
title: 'Invalid Start Date',
|
|
514
|
+
message: `Please enter a valid start date in the format ${format.value}`,
|
|
515
|
+
},
|
|
516
|
+
endDate: {
|
|
517
|
+
title: 'Invalid End Date',
|
|
518
|
+
message: `Please enter a valid end date in the format ${format.value}`,
|
|
519
|
+
},
|
|
520
|
+
range: {
|
|
521
|
+
title: 'Invalid Date Range',
|
|
522
|
+
message: 'End date must be after start date',
|
|
523
|
+
},
|
|
524
|
+
year: {
|
|
525
|
+
title: 'Invalid Year',
|
|
526
|
+
message: 'Year must be between the minimum and maximum allowed years',
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
const existingIndex = dateRangePickerErrors.value.findIndex((error) => error.title === warningProps[type].title);
|
|
531
|
+
if (existingIndex === -1) {
|
|
532
|
+
dateRangePickerErrors.value.push(warningProps[type]);
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
const clearWarningPropsValue = (type: 'startDate' | 'endDate' | 'range' | 'year') => {
|
|
537
|
+
const warningProps = {
|
|
538
|
+
startDate: 'Invalid Start Date',
|
|
539
|
+
endDate: 'Invalid End Date',
|
|
540
|
+
range: 'Invalid Date Range',
|
|
541
|
+
year: 'Invalid Year',
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
const index = dateRangePickerErrors.value.findIndex((error) => error.title === warningProps[type]);
|
|
545
|
+
if (index !== -1) {
|
|
546
|
+
dateRangePickerErrors.value.splice(index, 1);
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
// Update setModelValue to use format.value for parsing and formatting
|
|
551
|
+
const setModelValue = () => {
|
|
552
|
+
const startDateValid = validateDate(startMonthInput.value, startDateInput.value, startYearInput.value);
|
|
553
|
+
const endDateValid = validateDate(endMonthInput.value, endDateInput.value, endYearInput.value);
|
|
554
|
+
|
|
555
|
+
if (startDateValid && endDateValid) {
|
|
556
|
+
const startDate = `${startMonthInput.value}-${startDateInput.value}-${startYearInput.value}`;
|
|
557
|
+
const endDate = `${endMonthInput.value}-${endDateInput.value}-${endYearInput.value}`;
|
|
558
|
+
// Validate range
|
|
559
|
+
if (dayjs(startDate, format.value).isAfter(dayjs(endDate, format.value))) {
|
|
560
|
+
setWarningPropsValue('range');
|
|
561
|
+
return;
|
|
562
|
+
} else {
|
|
563
|
+
clearWarningPropsValue('range');
|
|
564
|
+
}
|
|
565
|
+
modelValue.value = {
|
|
566
|
+
startDate: dayjs(startDate, 'MMM-DD-YYYY').format(format.value),
|
|
567
|
+
endDate: dayjs(endDate, 'MMM-DD-YYYY').format(format.value),
|
|
568
|
+
};
|
|
569
|
+
emitRangeChange();
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
const validateDate = (month: string, date: string, year: string): boolean => {
|
|
574
|
+
if (!month || !date || !year) return false;
|
|
575
|
+
|
|
576
|
+
const monthObj = getMonthObject('monthValue', month);
|
|
577
|
+
if (!monthObj) {
|
|
578
|
+
setWarningPropsValue('startDate');
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const dayjsDate = dayjs(`${monthObj.monthValue + 1}-${date}-${year}`, 'M-D-YYYY');
|
|
583
|
+
if (!dayjsDate.isValid()) {
|
|
584
|
+
setWarningPropsValue('startDate');
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const yearNum = Number(year);
|
|
589
|
+
if (yearNum < minMaxYear.value.min || yearNum > minMaxYear.value.max) {
|
|
590
|
+
setWarningPropsValue('year');
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
clearWarningPropsValue('startDate');
|
|
595
|
+
clearWarningPropsValue('year');
|
|
596
|
+
return true;
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
const getMonthObject = (field: 'text' | 'fullText' | 'monthValue', value: string | number) => {
|
|
600
|
+
return monthsList.value.find((month) => month[field] === value);
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
const getDatePickerInputClasses = (width: string) => {
|
|
604
|
+
return `spr-w-[${width}] spr-min-w-[${width}]`;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
const getTabClasses = (tab: string) => {
|
|
608
|
+
return classNames('spr-cursor-pointer', {
|
|
609
|
+
'spr-background-color-pressed !spr-shadow-button': currentTab.value === tab,
|
|
610
|
+
});
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
const handleStartMonthInput = () => {
|
|
614
|
+
startMonthInput.value = startMonthInput.value.replace(/[^A-Za-z0-9\s]/g, '').toLocaleUpperCase();
|
|
615
|
+
handleConvertMonthIfValid('start');
|
|
616
|
+
setModelValue();
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
const handleStartDateInput = () => {
|
|
620
|
+
if (startDateInput.value.length === 2) {
|
|
621
|
+
const day = Number(startDateInput.value);
|
|
622
|
+
if (day < 1 || day > 31) {
|
|
623
|
+
startDateInput.value = '';
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
setModelValue();
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
const handleStartYearInput = () => {
|
|
631
|
+
if (startYearInput.value.length === 4) {
|
|
632
|
+
const year = Number(startYearInput.value);
|
|
633
|
+
if (year < minMaxYear.value.min || year > minMaxYear.value.max) {
|
|
634
|
+
startYearInput.value = '';
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
setModelValue();
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
const handleEndMonthInput = () => {
|
|
642
|
+
endMonthInput.value = endMonthInput.value.replace(/[^A-Za-z0-9\s]/g, '').toLocaleUpperCase();
|
|
643
|
+
handleConvertMonthIfValid('end');
|
|
644
|
+
setModelValue();
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
const handleEndDateInput = () => {
|
|
648
|
+
if (endDateInput.value.length === 2) {
|
|
649
|
+
const day = Number(endDateInput.value);
|
|
650
|
+
if (day < 1 || day > 31) {
|
|
651
|
+
endDateInput.value = '';
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
setModelValue();
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
const handleEndYearInput = () => {
|
|
659
|
+
if (endYearInput.value.length === 4) {
|
|
660
|
+
const year = Number(endYearInput.value);
|
|
661
|
+
if (year < minMaxYear.value.min || year > minMaxYear.value.max) {
|
|
662
|
+
endYearInput.value = '';
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
setModelValue();
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
const handleConvertMonthIfValid = (type: 'start' | 'end') => {
|
|
670
|
+
const monthInput = type === 'start' ? startMonthInput.value : endMonthInput.value;
|
|
671
|
+
const monthObj = monthsList.value.find(
|
|
672
|
+
(month) => month.text.toLowerCase() === monthInput.toLowerCase(),
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
if (monthObj) {
|
|
676
|
+
if (type === 'start') {
|
|
677
|
+
startMonthInput.value = monthObj.text;
|
|
678
|
+
} else {
|
|
679
|
+
endMonthInput.value = monthObj.text;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
const handleTabClick = (tab: string) => {
|
|
685
|
+
currentTab.value = tab;
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
const handleBackspace = (inputType: string, event: KeyboardEvent) => {
|
|
689
|
+
if (event && event instanceof KeyboardEvent && event.key === 'Backspace') {
|
|
690
|
+
// Start date fields
|
|
691
|
+
if (inputType === 'start-date' && startDateInput.value === '') {
|
|
692
|
+
nextTick(() => {
|
|
693
|
+
if (startMonthInputRef.value) startMonthInputRef.value.focus();
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
if (inputType === 'start-year' && startYearInput.value === '') {
|
|
697
|
+
nextTick(() => {
|
|
698
|
+
if (startDateInputRef.value) startDateInputRef.value.focus();
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
// End date fields
|
|
702
|
+
if (inputType === 'end-date' && endDateInput.value === '') {
|
|
703
|
+
nextTick(() => {
|
|
704
|
+
if (endMonthInputRef.value) endMonthInputRef.value.focus();
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
if (inputType === 'end-year' && endYearInput.value === '') {
|
|
708
|
+
nextTick(() => {
|
|
709
|
+
if (endDateInputRef.value) endDateInputRef.value.focus();
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
const updateInputFields = () => {
|
|
716
|
+
if (modelValue.value.startDate) {
|
|
717
|
+
const startDate = dayjs(modelValue.value.startDate, 'MM-DD-YYYY');
|
|
718
|
+
startMonthInput.value = startDate.format('MMM');
|
|
719
|
+
startDateInput.value = startDate.format('DD');
|
|
720
|
+
startYearInput.value = startDate.format('YYYY');
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (modelValue.value.endDate) {
|
|
724
|
+
const endDate = dayjs(modelValue.value.endDate, 'MM-DD-YYYY');
|
|
725
|
+
endMonthInput.value = endDate.format('MMM');
|
|
726
|
+
endDateInput.value = endDate.format('DD');
|
|
727
|
+
endYearInput.value = endDate.format('YYYY');
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
const emitRangeChange = () => {
|
|
732
|
+
const isValid = !dateRangePickerErrors.value.length;
|
|
733
|
+
emit('rangeChange', {
|
|
734
|
+
startDate: modelValue.value.startDate,
|
|
735
|
+
endDate: modelValue.value.endDate,
|
|
736
|
+
isValid,
|
|
737
|
+
});
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
const emitDateFormats = () => {
|
|
741
|
+
if (modelValue.value.startDate && modelValue.value.endDate) {
|
|
742
|
+
const startDate = dayjs(modelValue.value.startDate, 'MM-DD-YYYY');
|
|
743
|
+
const endDate = dayjs(modelValue.value.endDate, 'MM-DD-YYYY');
|
|
744
|
+
|
|
745
|
+
const formats = {
|
|
746
|
+
'MM-DD-YYYY': {
|
|
747
|
+
startDate: startDate.format('MM-DD-YYYY'),
|
|
748
|
+
endDate: endDate.format('MM-DD-YYYY'),
|
|
749
|
+
},
|
|
750
|
+
'YYYY-MM-DD': {
|
|
751
|
+
startDate: startDate.format('YYYY-MM-DD'),
|
|
752
|
+
endDate: endDate.format('YYYY-MM-DD'),
|
|
753
|
+
},
|
|
754
|
+
'MM/DD/YYYY': {
|
|
755
|
+
startDate: startDate.format('MM/DD/YYYY'),
|
|
756
|
+
endDate: endDate.format('MM/DD/YYYY'),
|
|
757
|
+
},
|
|
758
|
+
'DD-MM-YYYY': {
|
|
759
|
+
startDate: startDate.format('DD-MM-YYYY'),
|
|
760
|
+
endDate: endDate.format('DD-MM-YYYY'),
|
|
761
|
+
},
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
emit('getDateFormats', formats);
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
// Update emitInputValue to use format.value
|
|
769
|
+
const emitInputValue = () => {
|
|
770
|
+
emit('getInputValue', modelValue.value);
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
const emitMonthList = () => {
|
|
774
|
+
emit('getMonthList', monthsList.value);
|
|
775
|
+
};
|
|
776
|
+
|
|
777
|
+
const emitYearList = () => {
|
|
778
|
+
const years = Array.from(
|
|
779
|
+
{ length: minMaxYear.value.max - minMaxYear.value.min + 1 },
|
|
780
|
+
(_, i) => minMaxYear.value.min + i,
|
|
781
|
+
);
|
|
782
|
+
emit('getYearList', years);
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
const emitDateErrors = () => {
|
|
786
|
+
emit('getDateErrors', dateRangePickerErrors.value);
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
// #region - Watchers
|
|
790
|
+
watch(modelValue, () => {
|
|
791
|
+
updateInputFields();
|
|
792
|
+
emitDateFormats();
|
|
793
|
+
emitInputValue();
|
|
794
|
+
emitDateErrors();
|
|
795
|
+
}, { deep: true });
|
|
796
|
+
|
|
797
|
+
watch(dateRangePickerErrors, () => {
|
|
798
|
+
emitDateErrors();
|
|
799
|
+
}, { deep: true });
|
|
800
|
+
|
|
801
|
+
// #region - Lifecycle
|
|
802
|
+
onMounted(() => {
|
|
803
|
+
calendarTabUpdateCalendar();
|
|
804
|
+
yearsTabSetCurrentPageYear();
|
|
805
|
+
updateInputFields();
|
|
806
|
+
emitMonthList();
|
|
807
|
+
emitYearList();
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
const isDateRangePickerPopperDisabled = computed(() => {
|
|
811
|
+
return disabled.value || readonly.value;
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
// Provide a default for disabledDates to avoid undefined errors
|
|
815
|
+
const defaultDisabledDates = {
|
|
816
|
+
from: '',
|
|
817
|
+
to: '',
|
|
818
|
+
pastDates: false,
|
|
819
|
+
futureDates: false,
|
|
820
|
+
selectedDates: [],
|
|
821
|
+
weekends: false,
|
|
822
|
+
weekdays: false,
|
|
823
|
+
selectedDays: [],
|
|
824
|
+
};
|
|
825
|
+
const safeDisabledDates = computed(() => disabledDates?.value ?? defaultDisabledDates);
|
|
826
|
+
|
|
827
|
+
onClickOutside(dateRangePickerRef, () => {
|
|
828
|
+
datePopperState.value = false;
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
// #region - Positioning and Click Handling
|
|
832
|
+
// Check if user is using custom slot (not the default fallback)
|
|
833
|
+
const isUsingCustomSlot = computed(() => {
|
|
834
|
+
return !!slots.default;
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
// Dynamic placement based on which input was clicked (only for default inputs)
|
|
838
|
+
const dynamicPlacement = computed(() => {
|
|
839
|
+
// Get the base placement from props (top or bottom)
|
|
840
|
+
let basePlacement = props.placement;
|
|
841
|
+
|
|
842
|
+
if (basePlacement !== 'top' && basePlacement !== 'bottom') {
|
|
843
|
+
basePlacement = 'bottom';
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
if (clickedInputType.value === 'start') {
|
|
847
|
+
// For start date: concatenate base placement with 'start'
|
|
848
|
+
return `${basePlacement}-start`;
|
|
849
|
+
} else {
|
|
850
|
+
// For end date: concatenate base placement with 'end'
|
|
851
|
+
return `${basePlacement}-end`;
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
// Final placement: use dynamic for default inputs, standard for custom slots
|
|
856
|
+
const finalPlacement = computed(() => {
|
|
857
|
+
if (isUsingCustomSlot.value) {
|
|
858
|
+
return props.placement; // Use standard placement from props
|
|
859
|
+
} else {
|
|
860
|
+
return dynamicPlacement.value as (typeof PLACEMENTS_TYPES)[number]; // Use dynamic placement for default inputs
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
// Handle start date input clicks
|
|
865
|
+
const handleStartDateClick = () => {
|
|
866
|
+
if (disabled.value || readonly.value) return;
|
|
867
|
+
|
|
868
|
+
clickedInputType.value = 'start';
|
|
869
|
+
activeInputRef.value = startDateContainerRef.value;
|
|
870
|
+
datePopperState.value = true;
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
// Handle end date input clicks
|
|
874
|
+
const handleEndDateClick = () => {
|
|
875
|
+
if (disabled.value || readonly.value) return;
|
|
876
|
+
|
|
877
|
+
clickedInputType.value = 'end';
|
|
878
|
+
activeInputRef.value = endDateContainerRef.value;
|
|
879
|
+
datePopperState.value = true;
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
// Handle custom component clicks (for slot usage)
|
|
883
|
+
const handleCustomComponentClick = (event: Event) => {
|
|
884
|
+
if (disabled.value || readonly.value) return;
|
|
885
|
+
|
|
886
|
+
// For custom slots, use the clicked element as reference
|
|
887
|
+
activeInputRef.value = event.currentTarget as HTMLElement;
|
|
888
|
+
datePopperState.value = true;
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
return {
|
|
892
|
+
dateRangePickerClasses,
|
|
893
|
+
dateRangePickerRef,
|
|
894
|
+
startMonthInputRef,
|
|
895
|
+
startDateInputRef,
|
|
896
|
+
startYearInputRef,
|
|
897
|
+
endMonthInputRef,
|
|
898
|
+
endDateInputRef,
|
|
899
|
+
endYearInputRef,
|
|
900
|
+
startDateContainerRef,
|
|
901
|
+
endDateContainerRef,
|
|
902
|
+
activeInputRef,
|
|
903
|
+
datePopperState,
|
|
904
|
+
currentTab,
|
|
905
|
+
currentDate,
|
|
906
|
+
daysOfWeek,
|
|
907
|
+
monthsList,
|
|
908
|
+
startMonthInput,
|
|
909
|
+
startDateInput,
|
|
910
|
+
startYearInput,
|
|
911
|
+
endMonthInput,
|
|
912
|
+
endDateInput,
|
|
913
|
+
endYearInput,
|
|
914
|
+
dateRangePickerErrors,
|
|
915
|
+
calendarTabPageData,
|
|
916
|
+
calendarTabIsMinMonth,
|
|
917
|
+
calendarTabIsMaxMonth,
|
|
918
|
+
calendarTabUpdateCalendar,
|
|
919
|
+
calendarTabPrevMonth,
|
|
920
|
+
calendarTabNextMonth,
|
|
921
|
+
calendarTabIsRestDay,
|
|
922
|
+
calendarTabIsTodayIndicator,
|
|
923
|
+
calendarTabIsActiveMonthDates,
|
|
924
|
+
calendarTabIsInactiveMonthDates,
|
|
925
|
+
calendarTabIsSelectedDate,
|
|
926
|
+
calendarTabIsInRange,
|
|
927
|
+
calendarTabIsUnSelectedDate,
|
|
928
|
+
calendarTabIsDateIsDisabled,
|
|
929
|
+
calendarTabHandleDateInput,
|
|
930
|
+
monthTabHandleSelectedMonth,
|
|
931
|
+
yearTabCurrentYearPage,
|
|
932
|
+
yearTabGoToPreviousPage,
|
|
933
|
+
yearTabGoToNextPage,
|
|
934
|
+
yearTabIsPreviousButtonDisabled,
|
|
935
|
+
yearTabIsNextButtonDisabled,
|
|
936
|
+
yearTabHandleSelectedYear,
|
|
937
|
+
getMonthObject,
|
|
938
|
+
getDatePickerInputClasses,
|
|
939
|
+
getTabClasses,
|
|
940
|
+
isDateRangePickerPopperDisabled,
|
|
941
|
+
handleStartMonthInput,
|
|
942
|
+
handleStartDateInput,
|
|
943
|
+
handleStartYearInput,
|
|
944
|
+
handleEndMonthInput,
|
|
945
|
+
handleEndDateInput,
|
|
946
|
+
handleEndYearInput,
|
|
947
|
+
handleTabClick,
|
|
948
|
+
handleBackspace,
|
|
949
|
+
selectionMode,
|
|
950
|
+
isUsingCustomSlot,
|
|
951
|
+
dynamicPlacement,
|
|
952
|
+
finalPlacement,
|
|
953
|
+
handleStartDateClick,
|
|
954
|
+
handleEndDateClick,
|
|
955
|
+
handleCustomComponentClick,
|
|
956
|
+
};
|
|
957
|
+
};
|